package com.hh.workflow.service.impl;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.el.UelExpressionCondition;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.hh.baseframework.util.Check;
import com.hh.baseframework.util.Convert;
import com.hh.baseframework.util.MessageException;
import com.hh.baseframework.util.date.DateFormat;
import com.hh.baseframework.util.dto.ExtCheckTree;
import com.hh.baseframework.util.dto.PageRange;
import com.hh.hibernate.dao.inf.IHibernateDAO;
import com.hh.usersystem.bean.usersystem.HhXtYh;
import com.hh.usersystem.service.impl.LoginUserUtilService;
import com.hh.usersystem.service.impl.UserService;
import com.hh.workflow.util.SqlStatic;
import com.hh.workflow.util.Static;

@Service
public class TaskWfService extends ActivitiService {
	@Autowired
	private LoginUserUtilService loginUserUtilService;
	@Autowired
	private WorkFlowInfoService workFlowInfoService;
	@Autowired
	private ActivitiUtilService activitiUtilService;
	@Autowired
	private WorkFlowUtil workFlowUtil;
	@Autowired
	private UserService userService;
	@Autowired
	private IHibernateDAO<Object> dao;

	public List<Map<String, Object>> queryHiTaskListByAssignee(
			PageRange pageRange) {
		List<HistoricTaskInstance> historicTaskInstanceList = this.historyService
				.createHistoricTaskInstanceQuery()
				.taskAssignee(loginUserUtilService.findLoginUserId())
				.orderByHistoricActivityInstanceStartTime().desc()
				.listPage(pageRange.getStart(), pageRange.getEnd());
		return renderHiTask(historicTaskInstanceList, true);
	}

	public List<Map<String, Object>> queryHiTaskListByPiid(String piid) {
		List<HistoricTaskInstance> historicTaskInstanceList = this.historyService
				.createHistoricTaskInstanceQuery().processInstanceId(piid)
				.orderByHistoricActivityInstanceStartTime().desc().list();
		return renderHiTask(historicTaskInstanceList);
	}

	private List<Map<String, Object>> renderHiTask(
			List<HistoricTaskInstance> historicTaskInstanceList) {
		return renderHiTask(historicTaskInstanceList, false);
	}

	private List<Map<String, Object>> renderHiTask(
			List<HistoricTaskInstance> historicTaskInstanceList, boolean isEnd) {
		List<Map<String, Object>> taskMapList = new ArrayList<Map<String, Object>>();
		HistoricProcessInstance historicProcessInstance = null;
		for (HistoricTaskInstance historicTaskInstance : historicTaskInstanceList) {
			if (isEnd) {
				if (Check.isEmpty(historicTaskInstance.getEndTime())) {
					continue;
				}
			}
			if (historicProcessInstance == null) {
				historicProcessInstance = this
						.getHistoryService()
						.createHistoricProcessInstanceQuery()
						.processInstanceId(
								historicTaskInstance.getProcessInstanceId())
						.singleResult();
			}
			Map<String, Object> taskMap = workFlowUtil
					.taskToMap(historicTaskInstance);
			taskMap.put("piName", historicProcessInstance.getName());
			taskMapList.add(taskMap);
		}
		return taskMapList;
	}

	public Map<String, Object> queryTaskList(PageRange pageRange) {
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("userId", loginUserUtilService.findLoginUserId());
		String whereSql = "from act_ru_task art "
				+ " INNER JOIN act_ru_task_expand arte on art.ID_=arte.TASK_ID "
				+ " INNER JOIN act_hi_procinst ahp on art.PROC_INST_ID_=ahp.ID_ "
				+ " where USER_ID=:userId";
		Map<String, Object> resultMap = dao.queryPagingData("select "
				+ " art.ID_ id" + ",art.NAME_ name" + ",art.PROC_DEF_ID_ pdid "
				+ ",art.TASK_DEF_KEY_ activityId" + ",ahp.NAME piName"
				+ ",art.CREATE_TIME_ createTime" + " ,art.PROC_INST_ID_ piid"
				+ ",ahp.START_USER_ID_ startUserId "
				+ ",art.ASSIGNEE_ assignee  " + ",arte.USER_ID userId "
				+ whereSql, "select count(art.ID_) " + whereSql, paramMap,
				pageRange);
		List<Map<String, Object>> items = (List<Map<String, Object>>) resultMap
				.get("items");
		for (Map<String, Object> map : items) {
			if (Convert.toString(map.get("assignee")).equals(map.get("userId"))) {
				map.put("managerType", "主办");
			} else {
				map.put("managerType", "经办");
			}
		}

		return resultMap;

		// List<Map<String, Object>> taskMapList = new ArrayList<Map<String,
		// Object>>();
		// List<Task> tasks = this.taskService.createTaskQuery()
		// .taskAssignee(loginUserUtilService.findLoginUserId())
		// .orderByTaskCreateTime().desc().list();
		// for (Task task : tasks) {
		// Map<String, Object> taskMap = workFlowUtil.taskToMap(task);
		// HistoricProcessInstance historicProcessInstance = this
		// .getHistoryService().createHistoricProcessInstanceQuery()
		// .processInstanceId(task.getProcessInstanceId())
		// .singleResult();
		// taskMap.put("piName",historicProcessInstance.getName());
		// taskMap.put("group", "待办任务");
		// taskMapList.add(taskMap);
		// }
		//
		// List<Task> hxtasks = this.taskService.createTaskQuery()
		// .taskCandidateUser(loginUserUtilService.findLoginUserId())
		// .orderByTaskCreateTime().desc().list();
		// for (Task task : hxtasks) {
		// Map<String, Object> taskMap = workFlowUtil.taskToMap(task);
		// HistoricProcessInstance historicProcessInstance = this
		// .getHistoryService().createHistoricProcessInstanceQuery()
		// .processInstanceId(task.getProcessInstanceId())
		// .singleResult();
		// taskMap.put("piName",historicProcessInstance.getName());
		// taskMap.put("group", "候选任务");
		// taskMapList.add(taskMap);
		// }
		// return taskMapList;
	}

	public Map<String, Object> manager(String actionType, String activityId,
			String taskId) {
		String piid = "";
		String pdid = "";
		if ("select".equals(actionType)) {
			HistoricTaskInstance task = this.historyService
					.createHistoricTaskInstanceQuery().taskId(taskId)
					.singleResult();
			piid = task.getProcessInstanceId();
			pdid = task.getProcessDefinitionId();
		} else {
			Task task = this.taskService.createTaskQuery().taskId(taskId)
					.singleResult();
			piid = task.getProcessInstanceId();
			pdid = task.getProcessDefinitionId();
		}

		Map<String, Map<String, Object>> cellMaps = workFlowInfoService
				.findCellObjectListByPdid(pdid);
		Map<String, Object> activityMap = cellMaps.get(activityId);
		Map<String, Object> workflowMap = cellMaps.get(Static.WORKFLOW_MAP_KEY);
		workFlowInfoService.copyWfToAct(activityMap, workflowMap);

		HistoricProcessInstance processInstance = this.historyService
				.createHistoricProcessInstanceQuery().processInstanceId(piid)
				.singleResult();
		activityMap.put("objectId", processInstance.getBusinessKey());
		activityMap.put("taskId", taskId);
		activityMap.put("piid", processInstance.getId());

		return activityMap;
	}

	public void submit(Map<String, Object> paraMap,
			Map<String, String> userMap, Map<String, String> conditionMap)
			throws MessageException {

		String taskId = Convert.toString(paraMap.get("taskId"));
		// String piid = Convert.toString(paraMap.get("piid"));
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("formObject", paraMap);

		// Set<String> keysSet = userMap.keySet();
		// for (String string : keysSet) {
		// map.put(string, Convert.strToList(userMap.get(string)));
		// }
		map.putAll(userMap);
		map.putAll(conditionMap);
		this.claim(taskId);
		this.taskService.complete(taskId, map);
	}

	public void saveComment(Map<String, Object> paraMap) {
		String userId = loginUserUtilService.findLoginUserId();
		String taskId = Convert.toString(paraMap.get("taskId"));
		String piid = Convert.toString(paraMap.get("piid"));
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("taskId", taskId);
		paramMap.put("userId", userId);
		dao.deleteEntityBySql(SqlStatic.deleteCommentSql, paramMap);
		if (Check.isNoEmpty(paraMap.get("workFlowComment"))) {
			identityService.setAuthenticatedUserId(userId);
			taskService.addComment(taskId, piid, paraMap.get("workFlowComment")
					.toString());
		}
	}

	public List<ExtCheckTree> queryStepByActivityId(String pdid, String piid,
			String activityId) {
		List<ExtCheckTree> extCheckTrees = new ArrayList<ExtCheckTree>();
		ActivityImpl activityImpl = activitiUtilService.currentAct(pdid,
				activityId);
		List<PvmTransition> pvmTransitionList = activityImpl
				.getOutgoingTransitions();

		Map<String, Map<String, Object>> cellMaps = workFlowInfoService
				.findCellObjectListByPdid(pdid);

		for (PvmTransition pvmTransition : pvmTransitionList) {

			ExtCheckTree extCheckTree = new ExtCheckTree();
			extCheckTree.setIcon("/hhcommon/images/extjsico/17460346.png");
			Map<String, Object> propertys = new HashMap<String, Object>();
			propertys.put("activityParentType",
					activityImpl.getProperty("type"));

			ActivityImpl destination = (ActivityImpl) pvmTransition
					.getDestination();

			propertys.put("activityType", destination.getProperty("type"));
			propertys.put("activityId", destination.getId());

			Map<String, Object> activityMap = cellMaps.get(destination.getId());
			propertys.putAll(activityMap);

			UelExpressionCondition uelExpressionCondition = (UelExpressionCondition) pvmTransition
					.getProperty("condition");
			if (uelExpressionCondition != null) {
				String condition = uelExpressionCondition.getExpression()
						.toString().replace("${", "").replace("}", "");
				if (("1==" + destination.getId()).equals(condition)) {
					propertys.put("sdxz_condition", true);
				} else {
					propertys.put("condition", condition);
					propertys.put("expressionKeyList",
							Convert.expressionToListKey(condition));
					propertys.put("isChange", false);
					extCheckTree
							.setIcon("/hhcommon/images/icons/lock/lock.png");
					propertys.put("sdxz_condition", false);
				}
			}

			String activityTypeText = "";
			if ("exclusiveGateway".equals(destination.getProperty("type"))) {
				activityTypeText = "<font color=red>（单一分支）</font>";
			} else if ("userTask".equals(destination.getProperty("type"))) {
				activityTypeText = "<font color=red>（任务节点）</font>";
			} else if ("parallelGateway"
					.equals(destination.getProperty("type"))) {
				activityTypeText = "<font color=red>（并行分支）</font>";
			} else if ("inclusiveGateway".equals(destination
					.getProperty("type"))) {
				activityTypeText = "<font color=red>（任意分支）</font>";
			} else if ("inclusiveGateway".equals(destination
					.getProperty("type"))) {
				activityTypeText = "<font color=red>（任意分支）</font>";
			} else if ("startEvent".equals(destination.getProperty("type"))) {
				activityTypeText = "<font color=red>（结束节点）</font>";
			}
			extCheckTree.setId(destination.getId());
			extCheckTree.setText(Convert.toString(pvmTransition
					.getProperty("name"))
					+ Convert.toString(destination.getProperty("name"))
					+ activityTypeText);

			if ("userTask".equals(destination.getProperty("type"))) {
				extCheckTree.setLeaf(1);
			}
			extCheckTree.setExpanded(1);
			extCheckTree.setPropertys(propertys);
			extCheckTrees.add(extCheckTree);
		}
		if (extCheckTrees.size() == 1) {
			extCheckTrees.get(0)
					.setIcon("/hhcommon/images/icons/lock/lock.png");
			extCheckTrees.get(0).getPropertys().put("isChange", false);
			extCheckTrees.get(0).setChecked(true);
		}

		return extCheckTrees;
	}

	public InputStream findPicByPdid(String pdid) {
		ProcessDefinition procDef = repositoryService
				.createProcessDefinitionQuery()
				.processDefinitionId(pdid.toString()).singleResult();
		if (procDef != null) {
			String diagramResourceName = procDef.getDiagramResourceName();
			return repositoryService.getResourceAsStream(
					procDef.getDeploymentId(), diagramResourceName);
		}
		return null;
	}

	public List<Map<String, Object>> queryPicHiTask(String piid, String pdid) {
		ProcessDefinitionEntity def = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
				.getDeployedProcessDefinition(pdid);
		List<Map<String, Object>> resultListMap = new ArrayList<Map<String, Object>>();
		List<HistoricActivityInstance> historicActivityInstances = historyService
				.createHistoricActivityInstanceQuery().processInstanceId(piid)
				.orderByHistoricActivityInstanceEndTime().asc().list();
		for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
			ActivityImpl activityImpl = def
					.findActivity(historicActivityInstance.getActivityId());
			if ("userTask".equals(activityImpl.getProperty("type"))) {
				Map<String, Object> map = new HashMap<String, Object>();
				map.put("width", activityImpl.getWidth());
				map.put("height", activityImpl.getHeight());
				map.put("top", activityImpl.getY());
				map.put("left", activityImpl.getX());
				map.put("actid", activityImpl.getId());
				if (historicActivityInstance.getEndTime() == null
						|| "".equals(historicActivityInstance.getEndTime())) {
					map.put("src",
							"/hhcommon/opensource/mxgraph/examples/editors/wfimg/userTask_ru.gif");
				} else {
					map.put("src",
							"/hhcommon/opensource/mxgraph/examples/editors/wfimg/userTask_hi.gif");
				}
				resultListMap.add(map);
			}
		}
		return resultListMap;
	}

	public void claim(String taskId) {
		taskService.claim(taskId, loginUserUtilService.findLoginUserId());
	}

	public Map<String, Object> queryCommentByPiidAndTaskId(String piid,
			String taskId) {
		Map<String, Object> returnMap = new HashMap<String, Object>();

		List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
		List<Comment> comments = taskService.getProcessInstanceComments(piid);
		List<HistoricTaskInstance> taskInstances = historyService
				.createHistoricTaskInstanceQuery().processInstanceId(piid)
				.list();
		Map<String, HistoricTaskInstance> taskInstancesMap = Convert
				.listToMap(taskInstances);
		if (Check.isEmpty(comments)) {
			return returnMap;
		}
		for (Comment comment : comments) {
			if (taskId.equals(comment.getTaskId())
					&& comment.getUserId().equals(
							loginUserUtilService.findLoginUserId())) {
				returnMap.put("comment", comment.getFullMessage());
			} else {
				Map<String, Object> map = new HashMap<String, Object>();
				map.put("userId", comment.getUserId());
				map.put("message", comment.getFullMessage());
				map.put("time", DateFormat.dateToStr(comment.getTime()));
				map.put("piid", comment.getProcessInstanceId());
				map.put("taskId", comment.getTaskId());
				HhXtYh user = userService.findObjectById2(comment.getUserId());
				map.put("userName", user.getText());
				map.put("activityName",
						taskInstancesMap.get(comment.getTaskId()).getName());
				mapList.add(map);
			}
		}
		returnMap.put("commentList", mapList);
		return returnMap;
	}

	public List<String> queryCommentByTaskId(String taskId) {
		List<Comment> comments = taskService.getTaskComments(taskId);
		List<String> messageList = new ArrayList<String>();
		for (Comment comment : comments) {
			messageList.add(comment.getFullMessage());
		}
		return messageList;
	}

	public List<HhXtYh> queryHiAssigneesByActIdAndPiid(String piid,
			String activityId) {
		List<HistoricTaskInstance> historicTaskInstanceList = historyService
				.createHistoricTaskInstanceQuery().processInstanceId(piid)
				.taskDefinitionKey(activityId).list();
		List<String> userIdList = new ArrayList<String>();
		for (HistoricTaskInstance historicTaskInstance : historicTaskInstanceList) {
			if (Check.isNoEmpty(historicTaskInstance.getAssignee())) {
				userIdList.add(historicTaskInstance.getAssignee());
			}
		}
		if (Check.isEmpty(userIdList)) {
			return null;
		}
		return userService.queryListByIds(userIdList);
	}

	public void addTaskUser(String taskId, String userStrIds) {
		List<String> idList = Convert.strToList(userStrIds);
		for (String userId : idList) {
			taskService.addCandidateUser(taskId, userId);
		}

	}

}
